using ICSharpCode.TextEditor.Util;
using System;
using System.Collections.Generic;
using System.Drawing;
namespace ICSharpCode.TextEditor.Document
{
    public sealed class LineSegment : ISegment
    {
        internal LineSegmentTree.Enumerator treeEntry;
        private int totalLength;
        private int delimiterLength;
        private List<TextWord> words;
        private SpanStack highlightSpanStack;
        private WeakCollection<TextAnchor> anchors;
        public bool IsDeleted
        {
            get
            {
                return !this.treeEntry.IsValid;
            }
        }
        public int LineNumber
        {
            get
            {
                return this.treeEntry.CurrentIndex;
            }
        }
        public int Offset
        {
            get
            {
                return this.treeEntry.CurrentOffset;
            }
        }
        public int Length
        {
            get
            {
                return this.totalLength - this.delimiterLength;
            }
        }
        int ISegment.Offset
        {
            get
            {
                return this.Offset;
            }
            set
            {
                throw new NotSupportedException();
            }
        }
        int ISegment.Length
        {
            get
            {
                return this.Length;
            }
            set
            {
                throw new NotSupportedException();
            }
        }
        public int TotalLength
        {
            get
            {
                return this.totalLength;
            }
            internal set
            {
                this.totalLength = value;
            }
        }
        public int DelimiterLength
        {
            get
            {
                return this.delimiterLength;
            }
            internal set
            {
                this.delimiterLength = value;
            }
        }
        public List<TextWord> Words
        {
            get
            {
                return this.words;
            }
            set
            {
                this.words = value;
            }
        }
        public SpanStack HighlightSpanStack
        {
            get
            {
                return this.highlightSpanStack;
            }
            set
            {
                this.highlightSpanStack = value;
            }
        }
        public TextWord GetWord(int column)
        {
            int num = 0;
            foreach(TextWord current in this.words)
            {
                if(column < num + current.Length)
                {
                    return current;
                }
                num += current.Length;
            }
            return null;
        }
        public HighlightColor GetColorForPosition(int x)
        {
            if(this.Words != null)
            {
                int num = 0;
                foreach(TextWord current in this.Words)
                {
                    if(x < num + current.Length)
                    {
                        return current.SyntaxColor;
                    }
                    num += current.Length;
                }
            }
            return new HighlightColor(Color.Black, false, false);
        }
        public override string ToString()
        {
            if(this.IsDeleted)
            {
                return string.Concat(new object[]
				{
					"[LineSegment: (deleted) Length = ", 
					this.Length, 
					", TotalLength = ", 
					this.TotalLength, 
					", DelimiterLength = ", 
					this.delimiterLength, 
					"]"
				});
            }
            return string.Concat(new object[]
			{
				"[LineSegment: LineNumber=", 
				this.LineNumber, 
				", Offset = ", 
				this.Offset, 
				", Length = ", 
				this.Length, 
				", TotalLength = ", 
				this.TotalLength, 
				", DelimiterLength = ", 
				this.delimiterLength, 
				"]"
			});
        }
        public TextAnchor CreateAnchor(int column)
        {
            if(column < 0 || column > this.Length)
            {
                throw new ArgumentOutOfRangeException("column");
            }
            TextAnchor textAnchor = new TextAnchor(this, column);
            this.AddAnchor(textAnchor);
            return textAnchor;
        }
        private void AddAnchor(TextAnchor anchor)
        {
            if(this.anchors == null)
            {
                this.anchors = new WeakCollection<TextAnchor>();
            }
            this.anchors.Add(anchor);
        }
        internal void Deleted(ref DeferredEventList deferredEventList)
        {
            this.treeEntry = LineSegmentTree.Enumerator.Invalid;
            if(this.anchors != null)
            {
                foreach(TextAnchor current in this.anchors)
                {
                    current.Delete(ref deferredEventList);
                }
                this.anchors = null;
            }
        }
        internal void RemovedLinePart(ref DeferredEventList deferredEventList, int startColumn, int length)
        {
            if(length == 0)
            {
                return;
            }
            if(this.anchors != null)
            {
                List<TextAnchor> list = null;
                foreach(TextAnchor current in this.anchors)
                {
                    if(current.ColumnNumber > startColumn)
                    {
                        if(current.ColumnNumber >= startColumn + length)
                        {
                            current.ColumnNumber -= length;
                        }
                        else
                        {
                            if(list == null)
                            {
                                list = new List<TextAnchor>();
                            }
                            current.Delete(ref deferredEventList);
                            list.Add(current);
                        }
                    }
                }
                if(list != null)
                {
                    foreach(TextAnchor current2 in list)
                    {
                        this.anchors.Remove(current2);
                    }
                }
            }
        }
        internal void InsertedLinePart(int startColumn, int length)
        {
            if(length == 0)
            {
                return;
            }
            if(this.anchors != null)
            {
                foreach(TextAnchor current in this.anchors)
                {
                    if((current.MovementType == AnchorMovementType.BeforeInsertion) ? (current.ColumnNumber > startColumn) : (current.ColumnNumber >= startColumn))
                    {
                        current.ColumnNumber += length;
                    }
                }
            }
        }
        internal void MergedWith(LineSegment deletedLine, int firstLineLength)
        {
            if(deletedLine.anchors != null)
            {
                foreach(TextAnchor current in deletedLine.anchors)
                {
                    current.Line = this;
                    this.AddAnchor(current);
                    current.ColumnNumber += firstLineLength;
                }
                deletedLine.anchors = null;
            }
        }
        internal void SplitTo(LineSegment followingLine)
        {
            if(this.anchors != null)
            {
                List<TextAnchor> list = null;
                foreach(TextAnchor current in this.anchors)
                {
                    if((current.MovementType == AnchorMovementType.BeforeInsertion) ? (current.ColumnNumber > this.Length) : (current.ColumnNumber >= this.Length))
                    {
                        current.Line = followingLine;
                        followingLine.AddAnchor(current);
                        current.ColumnNumber -= this.Length;
                        if(list == null)
                        {
                            list = new List<TextAnchor>();
                        }
                        list.Add(current);
                    }
                }
                if(list != null)
                {
                    foreach(TextAnchor current2 in list)
                    {
                        this.anchors.Remove(current2);
                    }
                }
            }
        }
    }
}
